﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Routing;
using OfficeOpenXml;

namespace ASPMVCUtil.Helpers.Html.Grid
{
    /// <summary>
    /// Base class to format the grid cells
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public class GridCellTemplate<TModel>
    {
        public virtual string Draw(object value, TModel record)
        {
            return standardFormat(value);
        }

        public virtual void SetStyle(ExcelRange excelRange)
        {
            //Nothing;
        }

        public static string standardFormat(object value)
        {
            if (value != null)
            {
                TagBuilder span = new TagBuilder("span");
                span.MergeAttribute("title", value.ToString());
                span.InnerHtml = value.ToString();
                return span.ToString(TagRenderMode.Normal);
            }
            else
                return "";
        }
    }

    /// <summary>
    /// It puts an icon before the text of the cell
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public class GridCellTemplateIcon<TModel> : GridCellTemplate<TModel>
    {
        public string ImgSrc { get; protected set; }
        public bool ShowText { get; protected set; }

        public GridCellTemplateIcon(string imgSrc, bool showText = true)
            : base()
        {
            ImgSrc = imgSrc;
            ShowText = showText;
        }

        public override string Draw(object value, TModel record)
        {
            var img = new TagBuilder("img");
            img.MergeAttribute("src", ImgSrc);
            img.MergeAttribute("alt", "");

            if (ShowText)
            {
                TagBuilder span = new TagBuilder("span");
                span.MergeAttribute("style", "padding-left: 4px;");
                span.InnerHtml = value.ToString();
                return img.ToString(TagRenderMode.SelfClosing) + span.ToString(TagRenderMode.Normal);
            }
            else
                return img.ToString(TagRenderMode.SelfClosing);
        }
    }

    /// <summary>
    /// Puts a checkbox with the given id as the value of the cell, useful for forms
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public class GridCellTemplateCheckbox<TModel> : GridCellTemplate<TModel>
    {
        public string ID { get; protected set; }

        public GridCellTemplateCheckbox(string id)
            : base()
        {
            ID = id;
        }

        public override string Draw(object value, TModel record)
        {
            var check = new TagBuilder("input");
            check.MergeAttribute("type", "checkbox");
            check.MergeAttribute("name", ID);
            check.MergeAttribute("id", ID);
            check.MergeAttribute("value", value.ToString());

            return check.ToString(TagRenderMode.SelfClosing);
        }
    }

    /// <summary>
    /// Template that puts an image associated with ajax action. Should be added at view that contains the javascript functions: 
    /// onComplete{ActionName}(obj) onSuccess{ActionName}(context) onFailure{ActionName}(context)
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public abstract class GridCellTemplateImageAjaxAction<TModel> : GridCellTemplate<TModel>
    {
        /// <summary>
        /// Url to image
        /// </summary>
        public string ImgSrc { get; protected set; }
        public string IdPropertyName { get; protected set; }
        public AjaxHelper Ajax { get; protected set; }
        public string Acccion { get; protected set; }
        public bool RequestConfirmation { get; protected set; }
        public string ConfirmationMessage { get; protected set; }
        public RouteValueDictionary RouteValues { get; protected set; }

        public GridCellTemplateImageAjaxAction(string imgSrc, string idPropertyName, string ActionName, bool requestConfirmation, 
            AjaxHelper ajax, RouteValueDictionary routeValues, string confirmationMessage = null)
            : base()
        {
            ImgSrc = imgSrc;
            IdPropertyName = idPropertyName;
            Ajax = ajax;
            Acccion = ActionName;
            RequestConfirmation = requestConfirmation;
            RouteValues = routeValues;
            if (confirmationMessage == null)
            {
                ConfirmationMessage = GridResources.TemplateImageAjaxActionConfirmationMessage;
            }
            else
            {
                ConfirmationMessage = confirmationMessage;
            }
        }

        public override string Draw(object value, TModel record)
        {
            var propiedad = record.GetType().GetProperty(IdPropertyName);
            if (propiedad == null)
                throw new ArgumentException(string.Format(GridResources.InvalidInput1, IdPropertyName));
            string ID = null;
            if (propiedad.CanRead)
            {
                var valorId = propiedad.GetValue(record, null);
                if (valorId != null)
                {
                    ID = valorId.ToString();
                }
                else
                    throw new ArgumentException(string.Format(GridResources.InvalidInput2, IdPropertyName));
            }
            else
                throw new ArgumentException(string.Format(GridResources.InvalidInput3, IdPropertyName));
            MvcHtmlString eliminar = null;

            RouteValueDictionary routeValues = new RouteValueDictionary();
            routeValues.Add("id", ID);
            var obj = new {
                id = ID,

            };
            foreach (var routeValue in RouteValues)
            {
                routeValues.Add(routeValue.Key, routeValue.Value);
            }

            if (RequestConfirmation)
            {
                eliminar = ActionLinkAjax.ActionLinkImagen(Ajax, ImgSrc, Acccion,
                    Acccion, routeValues, new AjaxOptions
                    {
                        OnBegin = "function(){ return onBegin(this); }",
                        OnComplete = "function(){ return onComplete" + Acccion + "(this); }",
                        OnSuccess = "onSuccess" + Acccion,
                        OnFailure = "onFailure" + Acccion,
                        Confirm = ConfirmationMessage,
                        HttpMethod = "POST"
                    }, new { style = "border: 0px; margin: 2px;" });
            }
            else
            {
                eliminar = ActionLinkAjax.ActionLinkImagen(Ajax, ImgSrc, Acccion,
                    Acccion, routeValues, new AjaxOptions
                    {
                        OnBegin = "function(){ return onBegin(this); }",
                        OnComplete = "function(){ return onComplete" + Acccion + "(this); }",
                        OnSuccess = "onSuccess" + Acccion,
                        OnFailure = "onFailure" + Acccion,
                        HttpMethod = "POST"
                    }, new { style = "border: 0px; margin: 2px;" });
            }

            TagBuilder div = new TagBuilder("div");
            div.MergeAttribute("style", "text-align: center;");
            div.InnerHtml = eliminar.ToString();

            return div.ToString();
        }
    }

    /// <summary>
    /// Build a cell template from two others, printed 1 followed by the 2
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public abstract class GridCellTemplateCompound<TModel> : GridCellTemplate<TModel>
    {
        public GridCellTemplate<TModel> GridCellTemplate1 { get; set; }
        public GridCellTemplate<TModel> GridCellTemplate2 { get; set; }

        public override string Draw(object value, TModel record)
        {
            return GridCellTemplate1.Draw(value, record) + GridCellTemplate2.Draw(value, record);
        }
    }
}